package com.lx.boot.canal;

import com.alibaba.otter.canal.protocol.CanalEntry;
import com.alibaba.otter.canal.protocol.Message;
import com.lx.annotation.Note;
import com.lx.util.LX;
import org.checkerframework.checker.units.qual.A;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


public abstract class CanalService<T> {

    @Note("监听的表名,为空时监听所有")
    protected abstract String getTableName();

    protected abstract void notifiy(String tableName, CanalEntry.EventType eventType, CanalEntry.RowChange rowChange) throws Exception;

    protected List<T> getBefore(CanalEntry.RowChange rowChange){
        return rowChange.getRowDatasList().stream().map(v->(T)toBean(v.getBeforeColumnsList())).collect(Collectors.toList());
    }
    protected List<T> getAfter(CanalEntry.RowChange rowChange){
        return rowChange.getRowDatasList().stream().map(v->(T)toBean(v.getAfterColumnsList())).collect(Collectors.toList());
    }

    protected <A>List<A> getBefore(CanalEntry.RowChange rowChange, Class<A> aClass){
        return rowChange.getRowDatasList().stream().map(v->toBean(v.getBeforeColumnsList(),aClass)).collect(Collectors.toList());
    }
    protected <A>List<A> getAfter(CanalEntry.RowChange rowChange, Class<A> aClass){
        return rowChange.getRowDatasList().stream().map(v->toBean(v.getAfterColumnsList(),aClass)).collect(Collectors.toList());
    }

    protected List<Map<Object,Object>> toMap(CanalEntry.RowChange rowChange) {
        List<Map<Object,Object>> ls = new ArrayList<>();
        for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) {
            Map map = new HashMap<>();
            for (CanalEntry.Column column : rowData.getAfterColumnsList()) {
                if (!column.getIsNull()){
                    map.put(column.getName(), column.getValue());
                }
            }
            ls.add(map);
        }
        return ls;
    }
    private <A>A toBean(List<CanalEntry.Column> columns, Class<A> aClass) {
        Map map = new HashMap<>();
        for (CanalEntry.Column column : columns) {
            if (!column.getIsNull()){
                map.put(dealName(column.getName()), column.getValue());
            }
        }
        return LX.toObj(aClass, map);
    }
    private <T>T toBean(List<CanalEntry.Column> columns) {
        return toBean(columns, (Class<T>) getTClass());
    }

    @Note("获取当前类的泛型类型")
    private Class<T>  getTClass(){
        try {
            //返回表示此 Class 所表示的实体（类、接口、基本类型或 void）的直接超类的 Type。
            ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
            //返回表示此类型实际类型参数的 Type 对象的数组()，想要获取第二个泛型的Class，所以索引写1
            return (Class<T>)type.getActualTypeArguments()[0];//<T>
        }catch (Exception e){
            throw new RuntimeException("请检查是否添加实体注解:"+this.getClass().getName(),e);
        }
    }

    /** 说明: 表名转java类名
     * @author ylx 2023/4/21 18:24 */
    public static String dealName(String filed){
        String underline = "_";
        filed = filed.toLowerCase();
        StringBuilder sb = new StringBuilder(filed);
        int i = -1;
        while ((i=sb.indexOf(underline)) != -1){
            sb.deleteCharAt(i);
            if (i < sb.length()){
                int c = sb.charAt(i);
                if (i != 0 && c >='a' && c <='z'){
                    //转大写
                    sb.replace(i,i+1,(char)(c-32)+"");
                }
            }
        }
        return sb.toString();
    }



}
